package com.gmom.tako.network;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.util.Log;

import com.gmom.tako.model.Rss;


public class RssGetter {
	private static RssGetter parser = new RssGetter();
	public static RssGetter getInstance() {
		return parser;
	}
	private RssSaxHandler parseRssXml(String url) {
		SAXParserFactory saxParaser = SAXParserFactory.newInstance();

		RssSaxHandler sh = new RssSaxHandler();

		SAXParser saxp;
		try {
			saxp = saxParaser.newSAXParser();
			saxp.parse(url, sh);
		} catch (IOException ioe) { 
			
		} catch (Exception e) {
//			Log.e("RSS", "Rss-XmlParse", e);
		} finally {
		}
		return sh;
	}
	public List<Rss> parse(String url) {
		RssSaxHandler sh = parseRssXml(url);
		//Log.i("RSS", sh.getSiteTitle()+"");
		return sh.getParseResult();
	}
	
	public HashMap<String, String> parseMetadata(String url) {
		RssSaxHandler sh = parseRssXml(url);
		Log.i("RSS", "rssssss");
		HashMap<String, String> results = new HashMap<String, String>();
		results.put("title", sh.getSiteTitle());
		results.put("url", url);
		return results;
	}
	
	private static class RssSaxHandler extends DefaultHandler {

		private List<Rss> rssItems = null;
		private String siteTitle = "";
		private Rss currentItem;
		
		private boolean isChannel = false;
		private boolean isItem;
		private boolean isTitle = false;
		private boolean isDetail = false;
		private boolean isDate = false;
		private boolean isLink = false;
		
		private boolean isRoot = true;
		private RssTypeEnum rssType;
		
		@Override
		public void startElement(String uri, String localName, String qName,
				Attributes attributes) throws SAXException {
			if (isRoot) {
				if (localName.toLowerCase().equals(RssTypeEnum.RSS.getRoot())) {
					rssType = RssTypeEnum.RSS;
				} else if (localName.toLowerCase().equals(RssTypeEnum.RDF.getRoot())) {
					rssType = RssTypeEnum.RDF;
				} else if (localName.toLowerCase().equals(RssTypeEnum.ATOM.getRoot())) {
					rssType = RssTypeEnum.ATOM;
				}
				rssItems = new ArrayList<Rss>();
				siteTitle = "";
				isRoot = false;
			}
			if (rssType == null) return;
			setTagBool(localName, true);
			if (rssType.getEntryTag().equals(localName)) {
				isItem = true;
				currentItem = new Rss();
			}
		}

		@Override
		public void endElement(String uri, String localName, String qName)
				throws SAXException {
			if (rssType == null) return;
			setTagBool(localName, false);
			if (rssType.getEntryTag().equals(localName)) {
				isTitle = false;
				isDate = false;
				isDetail = false;
				isItem = false;
				isLink = false;
				currentItem.setUid(toInteger(makeHash(currentItem.getLink())));
				rssItems.add(currentItem);
				currentItem = null;
			}
		}
		
		private void setTagBool(String localName, boolean tf) {
			if (rssType.getMetaDataTag().equals(localName)) {
				isChannel = tf;
			}
			if (isItem) {
				if (rssType.getDateTag().equals(localName)) {
					isDate = tf;
				}
				if (rssType.getLinkTag().equals(localName)){
					isLink = tf;
				}
				if (rssType.getDetailTag().equals(localName)){
					isDetail = tf;
				}
			}
			if (isChannel && rssType.getTitleTag().equals(localName)) {
				isChannel = tf;
			}
			if (rssType.getTitleTag().equals(localName)){
				isTitle = tf;
			}
		}
		
		private byte[] makeHash(String value) {
			MessageDigest md5;
			try {
				md5 = MessageDigest.getInstance("MD5");
				md5.update(value.getBytes());
				byte[] hash = md5.digest();
				return hash;
			} catch (NoSuchAlgorithmException e) {
				//Log.e("MAKE_HASH", "hasherror", e);
			}
			return new byte[0];
		}
		
		private int toInteger(byte[] bytes) {
			DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
			try {
				return in.readInt();
			} catch (IOException e) {
				return 0;
			}
		}

		@Override
		public void characters(char[] ch, int start, int length)
				throws SAXException {
			if(isChannel) {
				if (isTitle) {
					this.siteTitle += new String(ch, start, length);
				}
			}
			if (currentItem == null) {
				return;
			}
			if (isItem) {
				if (isTitle) {
					String title = (currentItem.getTitle() == null) ? "" : currentItem.getTitle();
					currentItem.setTitle(new String(ch, start, length) + title);
				}
				if (isDetail) {
					String detail = (currentItem.getDetail() == null) ? "" : currentItem.getDetail();
					currentItem.setDetail(new String(ch, start, length) + detail);
				}
				if (isLink) {
					String link = (currentItem.getLink() == null) ? "" : currentItem.getLink();
					currentItem.setLink(new String(ch, start, length) + link);
				}
				if (isDate) {
					String date = (currentItem.getDate() == null) ? "" : currentItem.getDate();
					currentItem.setDate(new String(ch, start, length) + date);
				}
			}
		}
		
		public List<Rss> getParseResult(){
			return rssItems;
		}

		public String getSiteTitle() {
			return siteTitle;
		}
	}
}
